package com.seashop.util;

import lombok.extern.slf4j.Slf4j;
import okhttp3.*;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @author moredln
 * @desc
 * @date 2020-10-28 17:02
 */
@Slf4j
public class OkHttp3Util {

    /**
     *      * 懒汉 安全 加同步
     *      * 1.私有的静态成员变量 只声明不创建
     *      * 2.私有的构造方法
     *      * 3.提供返回实例的静态方法
     *      
     */
    private static OkHttpClient okHttpClient = null;


    private OkHttp3Util() {
    }

    public static OkHttpClient getInstance() {
        if (okHttpClient == null) {
            synchronized (OkHttp3Util.class) {
                if (okHttpClient == null) {
                    okHttpClient = new OkHttpClient.Builder()//构建器
                            .connectTimeout(60, TimeUnit.SECONDS)//连接超时
                            .writeTimeout(60, TimeUnit.SECONDS)//写入超时
                            .readTimeout(60, TimeUnit.SECONDS)//读取超时
                            .build();
                }
            }
        }
        return okHttpClient;
    }


    /**
     *      * get请求
     *      * 参数1 url
     *      * 参数2 回调Callback
     *      
     */

    public static String doGet(String oldUrl) {
        //创建OkHttpClient请求对象
        OkHttpClient okHttpClient = getInstance();
        //创建Request
        Request request = new Request.Builder().url(oldUrl).build();
        //得到Call对象
        Call call = okHttpClient.newCall(request);
        try {
            Response response = call.execute();
            assert response.body() != null;
            String result = response.body().string();
            return result;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     *      * get请求
     *      * 参数1 url
     *      * 参数2 回调Callback
     *      
     */
    public static String doGet(String oldUrl, Map<String, String> param) {
        //创建OkHttpClient请求对象
        OkHttpClient okHttpClient = getInstance();
        //创建Request
        if (param != null && param.size() > 0) {
            oldUrl += getNamValStr(param);
        }
        Request request = new Request.Builder().url(oldUrl).build();
        //得到Call对象
        Call call = okHttpClient.newCall(request);
        try {
            Response response = call.execute();
            assert response.body() != null;
            return response.body().string();
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return null;
    }


    /**
     *      * post请求
     *      * 参数1 url
     *      * 参数2 Map<String, String> params post请求的时候给服务器传的数据
     *      *      add..("","")
     *      *      add()
     *      
     */


    public static String doPost(String url, Map<String, String> params) {
        //创建OkHttpClient请求对象
        OkHttpClient okHttpClient = getInstance();
        //3.x版本post请求换成FormBody 封装键值对参数
        FormBody.Builder builder = new FormBody.Builder();
        //遍历集合,,,map集合遍历方式
        for (String key : params.keySet()) {
            builder.add(key, params.get(key));
        }
        //创建Request....formBody...new formBody.Builder()...add()....build()
        Request request = new Request.Builder().url(url).post(builder.build()).build();
        Call call = okHttpClient.newCall(request);
        try {
            Response response = call.execute();
            assert response.body() != null;
            String result = response.body().string();
            return result;
        } catch (IOException e) {
            log.error("okhttpUtil请求异常", e);
        }
        return null;
    }

    public static String doPost(String url, Map<String, String> params, List<String> repeatParams, String repeatKey) {
        //创建OkHttpClient请求对象
        OkHttpClient okHttpClient = getInstance();
        //3.x版本post请求换成FormBody 封装键值对参数
        FormBody.Builder builder = new FormBody.Builder();
        //遍历集合,,,map集合遍历方式
        for (String key : params.keySet()) {
            builder.add(key, params.get(key));
        }
        for (String val : repeatParams) {
            builder.add(repeatKey, val);
        }
        //创建Request....formBody...new formBody.Builder()...add()....build()
        Request request = new Request.Builder().url(url).post(builder.build()).build();
        Call call = okHttpClient.newCall(request);
        try {
            Response response = call.execute();
            assert response.body() != null;
            String result = response.body().string();
            return result;
        } catch (IOException e) {
            log.error("okhttpUtil请求异常", e);
        }
        return null;
    }

    /**
     *      * post请求上传文件....包括图片....流的形式传任意文件...
     *      * 参数1 url
     *      * file表示上传的文件
     *      * fileName....文件的名字,,例如aaa.jpg
     *      * params ....传递除了file文件 其他的参数放到map集合
     *      *
     *      
     */
    public static String uploadFile(String url, File file, String fileName, Map<String, String> params, Callback callback) {
        //创建OkHttpClient请求对象
        OkHttpClient okHttpClient = getInstance();
        //MultipartBody多功能的请求实体对象,,,formBody只能传表单形式的数据
        MultipartBody.Builder builder = new MultipartBody.Builder();
        builder.setType(MultipartBody.FORM);
        //参数
        if (params != null) {
            for (String key : params.keySet()) {
                builder.addFormDataPart(key, params.get(key));
            }
        }
        //文件...参数name指的是请求路径中所接受的参数...如果路径接收参数键值是file,此处应该改变
        builder.addFormDataPart("file", fileName, RequestBody.create(MediaType.parse("application/octet-stream"), file));
        //构建
        MultipartBody multipartBody = builder.build();
        //创建Request
        Request request = new Request.Builder().url(url).post(multipartBody).build();
        //得到Call
        Call call = okHttpClient.newCall(request);
        try {
            Response response = call.execute();
            assert response.body() != null;
            String result = response.body().string();
            return result;
        } catch (IOException e) {
            log.error("okhttpUtil请求异常", e);
        }
        return null;
    }


    /**
     *      * Post请求发送JSON数据....{"name":"zhangsan","pwd":"123456"}
     *      * 参数一：请求Url
     *      * 参数二：请求的JSON
     *      * 参数三：请求回调
     *      
     */
    public static String doPostJson(String url, String jsonParams) {
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), jsonParams);
        Request request = new Request.Builder().url(url).post(requestBody).build();
        Call call = getInstance().newCall(request);
        //得到Call
        try {
            Response response = call.execute();
            assert response.body() != null;
            String result = response.body().string();
            return result;
        } catch (IOException e) {
            log.error("okhttpUtil请求异常", e);
        }
        return null;
    }


    /**
     *      * 下载文件 以流的形式把apk写入的指定文件 得到file后进行安装
     *      * 参数er：请求Url
     *      * 参数san：保存文件的文件夹....download
     *      
     */
    public static void download(final String url, final String saveDir) {
        Request request = new Request.Builder().url(url).build();
        Call call = getInstance().newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                //com.orhanobut.logger.Logger.e(e.getLocalizedMessage());
            }

            @Override
            public void onResponse(Call call, final Response response) throws IOException {
                InputStream is = null;
                byte[] buf = new byte[2048];
                int len = 0;
                FileOutputStream fos = null;
                try {
                    //以字节流的形式拿回响应实体内容
                    is = response.body().byteStream();
                    //apk保存路径
                    final String fileDir = isExistDir(saveDir);
                    //文件
                    File file = new File(fileDir, getNameFromUrl(url));
                    fos = new FileOutputStream(file);
                    while ((len = is.read(buf)) != -1) {
                        fos.write(buf, 0, len);
                    }
                    fos.flush();

                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if (is != null) {
                        is.close();
                    }
                    if (fos != null) {
                        fos.close();
                    }
                }
            }
        });

    }

    /**
     *      * 判断下载目录是否存在......并返回绝对路径
     *      *
     *      * @param saveDir
     *      * @return
     *      * @throws IOException
     *      
     */

    public static String isExistDir(String saveDir) throws IOException {
        File rootPath = new File(saveDir);
        if (rootPath.exists()) {
            File downloadFile = new File("/", saveDir);
            if (!downloadFile.mkdirs()) {
                downloadFile.createNewFile();
            }
            String savePath = downloadFile.getAbsolutePath();
            return savePath;
        }
        return null;
    }

    /**
     *      * @param url
     *      * @return 从下载连接中解析出文件名
     *      
     */

    private static String getNameFromUrl(String url) {
        return url.substring(url.lastIndexOf("/") + 1);
    }

    private static String getNamValStr(Map<String, String> map) {
        StringBuilder str = new StringBuilder();
        Set<String> set = map.keySet();
        for (String key : set) {
            if (!(map.get(key) instanceof String)) {
                String ss = String.valueOf(map.get(key));
                str.append(key).append("=").append(ss).append("&");
            } else {
                str.append(key).append("=").append(map.get(key)).append("&");
            }
        }
        return str.toString().substring(0, str.lastIndexOf("&"));
    }
}
